<template>
  <div>
    <h3 @click="fn">我是根组件【msg: {{msg}}】</h3>
    <MyChild a="我是父组件的数据" b="BbB" @myfn="tt"></MyChild>
    <h5>{{ arr }}</h5> <button @click="changeArr">修改arr</button>
    <ul>
      <li v-for="(item,key) in obj">{{ key }} ==> {{ item }}</li>
    </ul>
    <h5 v-on:click="fnObj">点击修改obj</h5>

    <ul>
      <li v-for="(item, key) in obj2" :key="key"> {{ key }} ==> {{ item }}</li>
    </ul>
    <button @click="fnObj2">点击修改obj2</button>
    <div>name: {{ name }}</div> <button @click="modifyP('aa')">修改p触发修改name</button>
    
    <br/><br/><br/>
    通过解构获取id/name/age
    <div>{{ id }} == {{ name }} == {{ age }}</div>

    <button @click="isProxyFunction">检查元素是否为proxy</button>

    <ul>
      <li v-for="(item,key) in obj3">{{ key }} ==> {{ item }}</li>
    </ul>
    <button @click="changeLike">修改obj3的like</button>
  </div>
</template>

<script>
  /*
    1.setup必须return数据
    2.setup第一个参数是props
    第二个参数是上下文对象context
      1.emit 用来触发自定义事件
      2.props: 声明与使用的区别
      3.attrs:用来接收props没有声明的属性
      4.slots 拿到插槽元素
    3.ref：通过ref函数处理的数据变成了一个响应式对象，其中的value属性指向的是实际数据
      在模板中会自动解包
      作为响应式对象的属性也会自动解包。eg:reactive({name:ref('yeskip')}) name会自动解包
      1. ref是深层次的响应式，就算更改嵌套数组或对象依旧会触发视图的更新

    4.reactive专门处理数组和对象的
      弊端：1.数据类型有限
           2.不允许整体重新赋值
      为什么reactive整体重新赋值会丢失响应式而ref不会?
          reactive将对象变成了一个响应式对象；ref是把数据包裹在了一个响应式对象中
          3.解构后不具备响应式[ref也不具备]
    // ** 系统优化**
    5.shallowRef 不会深度监听，整体替换才会触发页面更新
    6. shallowReactive 只检测第一层级的数据变化

    7. triggerRef 强制触发一个浅层ref的更新
    8. readonly 被包裹的数据都不能修改[不管是响应式数据还是非响应式数据]
    9. shallowReadonly 只能把第一层级变成只读的

    10.isRef 判断一个数据是不是Ref包裹过的
    11. unref 完全等同于 isRef(val)?val.value:val
    12. toRef 把对象的某一个属性变成响应式。toRef('操作的对象',对象的属性)
        解构赋值会丢失响应式，可以使用toRef，不能使用ref().因为会重新生成一个新的响应式对象。
    13. toRefs 把对象每一个属性变成响应式
    14. toValue 返回值，参数可以是函数，相当于调用后返回值
    15.isProxy reactive、readonly shallowReactive、shallowReadonly会创建代理对象；而ref是创建了一个对象，包裹了原来数据。 
    16.isReactive 判断是否是reactive或者shallowReactive对象
       isReadonly 判断是否是readonly或者shallowReadonly对象
    17.toRaw 返回一个创建代理对象的原始数据(数据本身)
    18.markRaw 标记一个对象，让它永远不会成为响应式对象 [把一些对象属性变为非响应式]

    19.生命周期函数:
      选项式api: beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeUnmount、unmounted
                创建前后、挂载前后、更新前后、卸载前后
  */
  import MyChild from './pages/MyChild.vue';
  import {ref,reactive,shallowRef, shallowReactive, triggerRef, readonly, isRef, unref, toRef, toRefs,isProxy, markRaw} from 'vue'
  export default {
    setup(){
      let msg = ref("hello");
      let arr = reactive([0,1,2,3,4,5,6]) 
      const p = reactive({id:'123456',name:'小明',age:18})
      let obj = shallowRef({id:'123456',name:'小明',age:18})
      let obj2 = shallowReactive({name:'小明',age:18,like:['draw','singe','dance']})
      const copy = readonly(ref(obj))
      // copy.value.name='tom' // [Vue warn] Set operation on key "name" failed: target is readonly.

      console.log("是不是ref包裹的", isRef(arr));
      console.log('unref获取值:',unref(msg));
      
      
      let name = toRef(p,'name')
      console.log(name.value);
      // const illegalName = ref(p.name) // 完全和p脱离关系，重新生成了一个响应式对象，不具备和p关联的特征

      let p2 = toRefs(p)
      console.log(`p2->`,p2)
      
      function isProxyFunction(){
        console.log(`msg is proxy ? ->`, isProxy(msg))  // false
        console.log(`arr is proxy? ->`,isProxy(arr))    // true
        console.log(`obj is proxy? ->`,isProxy(obj))    // true
        console.log(`obj2 is proxy? ->`,isProxy(obj2))  // true
      }

      let obj3 = reactive({name:'张三',age:18})
      let like = ['吃饭','睡觉']
      obj3.like = markRaw(like) // 如果不添加markRow，后续添加的属性也是响应式的。
      // 修改后like[0]不会发生变化
      function changeLike() {
        // 如果修改like[0]
        obj3.like[0] = '打游戏'
        console.log(`obj3 like ->`,obj3.like)
      }
        

      function modifyP(){
        p.name = '小红'// 检查name会不会变
      }


      function fnObj(){
        console.log('触发修改name');
        // obj.value.name='小红' // 不会触发修改
        obj.value.id='23456'
        triggerRef(obj) // 强制更新obj的id属性
        // obj.value = {name:'小红',age:22}
      }

      function fnObj2() {
        console.log('触发修改obj2')
        obj2.like[0] = 'basketball'
        // obj2.like = ['basketball','cooke','walk']
      }
      function fn(){

        console.log("哈哈哈");
      }
      function tt(param){
        msg.value = '修改后的msg内容'
        console.log('子组件通知父组件成功参数: ' + param)
      }
      function changeArr() {
        arr[0] == 100 ? arr[0] = 0: arr[0] =100
      }
      return {msg,fn,tt,changeArr,arr,obj,fnObj,obj2,fnObj2
             ,modifyP, ...p2, isProxyFunction, obj3,changeLike
      }
    },
    components:{
      MyChild
    }
  }
</script>

<style scoped>
 
</style>